	#ifndef __GLF_FILESTREAMIMPL_H_INCLUDED__
#define __GLF_FILESTREAMIMPL_H_INCLUDED__

#include <glf/io/stream.h>
#include <glf/core/atomic.h>

namespace glf {

class FileStream;

class FileStreamImpl : public IOStream {

	friend struct ReadASyncThread;

public:
#if GLF_USE_FILESTREAM_DBGSTATS
	struct DBGStats
	{
		unsigned int numSeeks;

		unsigned int numReads;
		unsigned int numBytesRead;
	
		unsigned int numWrites;
		unsigned int numBytesWritten;
	};
	DBGStats mDebugStats;
	const DBGStats& GetDBGStats() const { return mDebugStats;}
#endif //GLF_USE_FILESTREAM_DBGSTATS

	FileStreamImpl();
	FileStreamImpl(const char* filename, openflag flag = read|loc_data);
	virtual ~FileStreamImpl();

	bool Open(const char* filename, openflag flag = read|loc_data);
	virtual void Close();

	virtual size_t GetSize() const;
	
	virtual bool Seek(int offset, seek origin);
	virtual size_t Peek(void* buffer, size_t size);
	//void Cancel();
	bool CancelAsync(Callback callback, void* arg);
	
	virtual bool CanSeek() const;
	//bool CanCancel() const;
	virtual bool CanRead  () const;
	virtual bool CanWrite () const;

	int WaitASync(size_t ms) const;
	virtual size_t Tell()  const;
	
	bool IsEof() const;

	virtual size_t Read(void* buffer, size_t size);
	virtual size_t ReadWithOffset(void* buffer, size_t size, size_t offset);
	//bool ReadASync(void* buffer, size_t size, Callback callback, void* arg);
#if GLF_VIRTUAL_FILESTREAM
	virtual bool ReadASync(FileStream* fs, void* buffer, size_t size, size_t offset, Callback callback, void* arg);
#else
	virtual bool ReadASync(void* buffer, size_t size, size_t offset, Callback callback, void* arg);
#endif
	virtual size_t Write(const void* buffer, size_t size);
	//bool WriteASync(const void* buffer, size_t size, Callback callback, void* arg);

	openflag CopyPath(char* dst, size_t len) const;
	const char* GetPath(openflag& loc) const;
	const char* GetFilename() const;

	static void DispatchDoneReads();

private:
    
    bool CheckCrc(const char* filename);
	
	bool _Open(const char* filename, openflag flag, bool isUsingArchive);
	stringc mFullPath;
	openflag mFlag;
	Atomic32 mAsyncCount;

	GLF_DECLARE_IMPL(320)
};

#if GLF_USE_FILESTREAM_CALLBACK
class FileStreamCallback
{
public:
	virtual ~FileStreamCallback() {}
	virtual void OnOpen(FileStreamImpl* fs, const char* filename, ios::openflag flag, bool isOpen) = 0;
	virtual void OnSeek(FileStreamImpl* fs, const char* filename, int offset, ios::seek origin, bool success) = 0;
	virtual void OnRead(FileStreamImpl* fs, const char* filename, void* buffer, size_t size, size_t numRead) = 0;
	virtual void OnWrite(FileStreamImpl* fs, const char* filename, const void* buffer, size_t size, size_t numWritten) = 0;
	virtual void OnClose(FileStreamImpl* fs, const char* filename) = 0;
};

extern FileStreamCallback* GetFileStreamCallback();

#endif	//GLF_USE_FILESTREAM_CALLBACK

} //namespace glf
#endif
